package com.disgruntledbots;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Stack;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class ReplayPhysicsUpdater {

	JSONObject replay;
	ArrayList<PhysicsEntityConnector> mObjects;
	Stack<JSONArray> turnStack;
	Stack<JSONObject> newObjectStack;
	boolean done;
	
	public ReplayPhysicsUpdater(JSONObject replayData, ArrayList<PhysicsEntityConnector> physObjects) throws NullPointerException
	{
		replay = replayData;
		mObjects = physObjects;
		
		turnStack = new Stack<JSONArray>();
		newObjectStack = new Stack<JSONObject>();

		done = false;
		
		try {
			this.loadTurnStack();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(replayData == null || physObjects == null)
		{
			throw new NullPointerException("No Null parameters in ReplayPhysicsUpdater constructor");
		}
	}
	
	public void update()
	{
		JSONArray jArray;
		ArrayList<JSONObject> jObjArray = new ArrayList<JSONObject>();
		ArrayList<PhysicsEntityConnector> removeList = new ArrayList<PhysicsEntityConnector>();

		JSONObject tmp;

		Log.i("Replay", "object list deserialized");

		jArray = turnStack.pop();
		for(int i = 0; i < jArray.length(); i++)
		{
			try{
				tmp = jArray.getJSONObject(i);
				jObjArray.add(tmp);
			}catch (JSONException e) {
				// TODO Auto-generated catch block
				Log.e("Reply", "unable to get JSONObject", e);
			}
		}



		for(PhysicsEntityConnector p : mObjects){
			boolean found = false;
			if(p != null){
				for(JSONObject j : jObjArray)
				{
					String name  = null;
					float posX;
					float posY;
					float velX;
					float velY;
					float angle;
					float angularVelocity;
					
					try{

						try{
							name = j.getString(PhysicsJSONSerializer.id);
						}
						catch(JSONException e){

						}

						try{
							if(p.name.compareTo(name)==0)
							{
								found = true;
								posX = Float.parseFloat(j.getJSONObject("Position").getString("X"));
								posY = Float.parseFloat(j.getJSONObject("Position").getString("Y"));
								angle = Float.parseFloat(j.getString("Angle"));
								p.mBody.setTransform(posX, posY, angle);

								velX = Float.parseFloat(j.getJSONObject("LinearVelocity").getString("X"));
								velY = Float.parseFloat(j.getJSONObject("LinearVelocity").getString("Y"));
								p.mBody.setLinearVelocity(velX, velY);

								angularVelocity = Float.parseFloat(j.getString("AngularVelocity"));


							}
						}catch(JSONException e)
						{
							Log.wtf("Replay", "failed to deserialize object data", e);
						}catch(NullPointerException e2)
						{
							Log.wtf("Replay", "Null object referenced", e2);
						}
					}catch(NullPointerException e)
					{

					}
				}
			}

			if(!found)
			{
				try{
					p.dispose();
				}catch(NullPointerException e)
				{
					
				}
				
				removeList.add(p);
			}

		}

		try{
			done = turnStack.peek() == null;
		}catch(EmptyStackException e)
		{
			done = true;
		}
		synchronized(this){
			mObjects.removeAll(removeList);
		}
		mObjects.trimToSize();
	}
	
	public void loadTurnStack() throws JSONException
	{
		JSONArray jArray;
		jArray = replay.getJSONArray("Step: Final");
		turnStack.push(jArray);
	}
	
	public void dispose()
	{
		mObjects = null;
		replay = null;
	}
	
	public boolean isDone()
	{
		return done;	
	}
}
